﻿module Sustainalytics.Pager {
    import Common = Sustainalytics.Common;

    export class PagerController {
        // associated scope
        $scope: ng.IScope;

        // paging options
        pagingOptions: Common.PagingOptions;

        // total number of items
        totalItemsCount: number = 0;

        // total number of pages
        totalPageCount: number = 0;

        // visible pages
        visiblePages: number = 5;
        visiblePagesFrom: number = 1;
        visiblePagesTo: number = 1;
        visiblePagesArray: number[];


        // Ctor.
        constructor($scope: ng.IScope) {

            var ctrl = this;

            ctrl.$scope = $scope;            

            // init paging options
            ctrl.pagingOptions = new Common.PagingOptions(1, 20);

            // set initial visible pages
            ctrl.visiblePages = 5;

            $scope['pager'] = this;

            $scope.$watch('pager.visiblePages', function () {
                ctrl.computeVisiblePages();
            });
            $scope.$watch('pager.totalPageCount', function () {
                ctrl.computeVisiblePages();
            });
            $scope.$watch('pager.pagingOptions.pageIndex', function () {
                ctrl.computeVisiblePages();
            });
            $scope.$watch('pager.totalItemsCount', function () {
                ctrl.computeTotalPageCount();
            });
            $scope.$watch('pager.pagingOptions.pageSize', function ()
            {
                ctrl.computeTotalPageCount();
                ctrl.pagingOptions.pageIndex = 1;
                ctrl.emitPagingOptionsChanged();
            });                      

            ctrl.computeVisiblePages();
            ctrl.computeTotalPageCount();

            // fire changed event
            this.emitPagingOptionsChanged();
        }

        // get visible pages
        public computeVisiblePages() {
            var from = 0;
            var to = 0;
            var pageIndex = this.pagingOptions.pageIndex;
            var visiblePages = this.visiblePages;
            var totalPageCount = this.totalPageCount;

            // compute how many pages to display before and after current page
            var prevPages = Math.floor(visiblePages / 2);
            var nextPages = visiblePages - 1 - prevPages;

            // compute visible pages range
            var from = pageIndex - prevPages;
            var to = pageIndex + nextPages;

            if (from < 1) {
                from = 1;
                to = visiblePages;
            }
            else {
                if (to > totalPageCount) {
                    to = totalPageCount;
                    from = totalPageCount - visiblePages + 1;
                }
            }

            // fix from inclusive
            if (from < 1) {
                from = 1;
            }

            // fix to inclusive
            if (to > this.totalPageCount)
                to = this.totalPageCount;

            // create the array of visible pages
            var visiblePagesArray = new Array();
            for (var index = from; index <= to; index++) {
                visiblePagesArray.push(index);
            }

            this.visiblePagesFrom = from;
            this.visiblePagesTo = to;
            this.visiblePagesArray = visiblePagesArray;
        }

        // total number of pages
        public computeTotalPageCount() {
            this.totalPageCount = Math.ceil(this.totalItemsCount / this.pagingOptions.pageSize);
        }

        // number of items to take
        public takeCount(): number {
            return this.pagingOptions.pageSize;
        }

        // number of items to skip
        public skipCount(): number {
            return (this.pagingOptions.pageIndex - 1) * this.pagingOptions.pageSize;
        }

        // go to previous page
        public prev() {            
            if (this.pagingOptions.pageIndex > 0) {

                // decrement page index
                this.pagingOptions.pageIndex -= 1;

                // trigger changed event
                this.emitPagingOptionsChanged();
            }
        }

        // go to next page
        public next() {
            if (this.pagingOptions.pageIndex < this.totalPageCount) {
                
                // increment page index
                this.pagingOptions.pageIndex += 1;

                // trigger changed event
                this.emitPagingOptionsChanged();
            }
        }

        public prevSet() {
            // keep old page index
            var oldPageIndex = this.pagingOptions.pageIndex;

            // compute new page index
            var newPageIndex = this.pagingOptions.pageIndex - this.visiblePages;

            // fix new page index
            if (newPageIndex < 1) {
                newPageIndex = 1;
            }

            // set new page index and trigger event
            if (oldPageIndex !== newPageIndex) {
                this.pagingOptions.pageIndex = newPageIndex;
                this.emitPagingOptionsChanged();
            }
        }

        public nextSet() {
            // keep old page index
            var oldPageIndex = this.pagingOptions.pageIndex;

            // compute new page index
            var newPageIndex = this.pagingOptions.pageIndex + this.visiblePages;

            // fix new page index
            if (newPageIndex > this.totalPageCount) {
                newPageIndex = this.totalPageCount;
            }

            // set new page index and trigger event
            if (oldPageIndex !== newPageIndex) {
                this.pagingOptions.pageIndex = newPageIndex;
                this.emitPagingOptionsChanged();
            }
        }

        // go to specific page
        public goTo(pageIndex: number) {
            if (this.pagingOptions.pageIndex !== pageIndex) {

                // set page index
                this.pagingOptions.pageIndex = pageIndex;

                // trigger changed event
                this.emitPagingOptionsChanged();
            }
        }

        // trigger pagingOptionsChanged event giving as argument current controller data
        private emitPagingOptionsChanged() {
            this.$scope.$emit('pagerChanged', this);
        }

        // load paging options from PagedList
        public loadPagingFromPagedList(pagedList: Common.PagedList<{}>) {
            var ctx = this;

            ctx.totalItemsCount = pagedList.totalItemsCount;
            ctx.pagingOptions = pagedList.pagingOptions;
        }
    }


    // get pager module
    var pagerModule = angular.module('Sustainalytics.Pager');

    // register pager controller
    pagerModule.controller('PagerController', function ($scope) {
        var controller = new Sustainalytics.Pager.PagerController($scope);
    });
}